# coding=utf-8
from __future__ import print_function, absolute_import
from gm.api import *
from dingding import *

import winsound
import datetime
import numpy as np
import pandas as pd

import pyttsx3
engine = pyttsx3.init()
# ==============================================================
# 读取文本文件
file_path = 'E:\\自选股.EBK'  # 替换为你的文件路径
data = pd.read_csv(file_path, delimiter='\t', header=None, dtype=str)
# 将DataFrame转换为字符串列表
string_list = data.iloc[:, 0].tolist()

# 替换第一个字符
modified_string_list = [
    'SHSE.' + s[1:] if s.startswith(('1', '2')) else 'SZSE.' + s[1:] if s.startswith('0') else s
    for s in string_list
]
symbols_string = ','.join(modified_string_list)
# ==============================================================


def init(context):
    context.frequency = '300s'
    context.short = 60
    context.long = 120
    context.period = context.long + 1
    # context.index='SHSE.000016'
    # context.constituent_stock = get_history_constituents(index=context.index, start_date='2024-07-09', end_date='2024-7-10')[0]['constituents'].keys()
    context.fields = 'close'
    context.volume=100
    context.eob_tmp=context.now #初始化eob_tmp时间格式,用于on_bar中

    context.symbol = symbols_string
    subscribe(context.symbol, 
                context.frequency, 
                count=context.period, 
                unsubscribe_previous=True)
def on_bar(context, bars):
    
    account = context.account()
    cash = account.cash
    eob_time=bars[0]['eob']
    if context.eob_tmp!=eob_time:#由于多个品种,时间会重复打印,去掉重复
        print(f"计时:{eob_time.strftime('%Y-%m-%d %H:%M:%S')[10:19]},\
                可用资金: {cash['available']:.2f},\
                账户的浮动盈亏: {cash['pnl']:.2f},\
                账户的累计盈亏:{cash['cum_pnl']:.2f}")
        context.eob_tmp=eob_time

    symbol = bars[0]['symbol']
    # 获取历史数据
    data = context.data(symbol, context.frequency, context.period, fields=context.fields)
    short_avg  = data['close'].rolling(context.short).mean()
    long_avg  = data['close'].rolling(context.long).mean()

    if short_avg.values[-1] > long_avg.values[-1] and short_avg.values[-2] < long_avg.values[-2]:
        print(f'{context.now}, {symbol} 金叉, 周期{context.frequency}, 均线参数{context.short},{context.long}')
        order_volume(symbol=symbol,
                        volume=context.volume,
                        side=OrderSide_Buy,
                        position_effect=PositionEffect_Open,
                        order_type=OrderType_Market)
        # 播放报警声
        # winsound.Beep(1000, 2000)  # 参数：频率（Hz），持续时间（毫秒）
        attribute = '你好！买入 '
        sym=f'{symbol}'
        message =  " ".join(['通知：', attribute, sym])
        result = send_dingtalk_message(webhook_url, message, at_mobiles, is_at_all)
        print(result)
        # 使用 pyttsx3 播报变量属性
        engine.say(attribute)
        engine.runAndWait()
    elif short_avg.values[-1] < long_avg.values[-1] and short_avg.values[-2] > long_avg.values[-2]:
        print(f'{context.now}, {symbol} 死叉, 周期{context.frequency}, 均线参数{context.short},{context.long}')
        order_volume(symbol=symbol,
                        volume=context.volume,
                        side=OrderSide_Sell,
                        position_effect=PositionEffect_Open,
                        order_type=OrderType_Market)
        # 播放报警声
        # winsound.Beep(1000, 2000)  # 参数：频率（Hz），持续时间（毫秒）
        attribute ='你好！卖出 '
        sym=f'{symbol}'
        message =  " ".join(['通知：', attribute, sym])
        result = send_dingtalk_message(webhook_url, message, at_mobiles, is_at_all)
        print(result)
        # 使用 pyttsx3 播报变量属性
        engine.say(attribute)
        engine.runAndWait()

    # print(context.now)
    
def on_backtest_finished(context, indicator):
    print('*' * 50)
    print('回测已完成，请通过右上角“回测历史”功能查询详情。')

if __name__ == '__main__':
    '''
        strategy_id策略ID, 由系统生成
        filename文件名, 请与本文件名保持一致
        mode运行模式, 实时模式:MODE_LIVE回测模式:MODE_BACKTEST
        token绑定计算机的ID, 可在系统设置-密钥管理中生成
        backtest_start_time回测开始时间
        backtest_end_time回测结束时间
        backtest_adjust股票复权方式, 不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POST
        backtest_initial_cash回测初始资金
        backtest_commission_ratio回测佣金比例
        backtest_slippage_ratio回测滑点比例
        backtest_match_mode市价撮合模式，以下一tick/bar开盘价撮合:0，以当前tick/bar收盘价撮合：1
        '''
    run(strategy_id='03c7895c-4011-11ef-98e7-0050b6c7fa6e',
        filename='main.py',
        mode=MODE_BACKTEST,
        token='ca9c4532786a122aa5ceb3fd726432862e046f91',
        backtest_start_time='2024-07-09 08:00:00',
        backtest_end_time='2024-07-10 16:00:00',
        backtest_adjust=ADJUST_PREV,
        backtest_initial_cash=10000000,
        backtest_commission_ratio=0.0001,
        backtest_slippage_ratio=0.0001,
        backtest_match_mode=1)

